package world;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.math.BigDecimal;
import java.util.ArrayList;

import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import world.edges.Border;
import world.edges.Door;
import world.edges.Wall;
import world.placement.Direction;
import world.placement.Position;
import world.square.NormalTeleport;
import world.square.Rock;
import world.square.Square;
import world.square.Temperature;
import world.square.TemperatureScale;
import world.square.Transparent;



public class DungeonTest {
	
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		dungeon = new Level<Square>(20, 20);
		
		square000 = new Square(Direction.NORTH);
		square000.addBorders(new Border(new Wall(false), Direction.EAST), new Border(new Wall(false), Direction.WEST));
		square100 = new Square();
		square100.addBorders(new Border(new Wall(false), Direction.SOUTH));

		square010 = new Square(Direction.WEST);
		square010.setHasSlipperyFloor(true);
		square010.addBorders(new Border(new Door(false), Direction.EAST),new Border(new Wall(false), Direction.SOUTH));

		square110 = new Square(Direction.EAST);
		square110.addBorders(new Border(new Wall(false), Direction.EAST));

		square020 = new Square(Direction.EAST);
		square120 = new Square(Direction.EAST);
		square120.addBorders(new Border(new Wall(true), Direction.SOUTH));
		square120.addBorders(new Border(new Wall(true), Direction.WEST));	
		
		position000 = new Position (0, 10, 0);
		position100 = new Position (1, 10, 0);
		position010 = new Position (0, 11, 0);

		dungeon.addSquare(square000, new Position (0, 10, 0));
		dungeon.addSquare(square100, new Position (1, 10, 0));
		dungeon.addSquare(square010, new Position (0, 11, 0));
		dungeon.addSquare(square110, new Position (1, 11, 0));
		dungeon.addSquare(square020, new Position (0, 12, 0));
		dungeon.addSquare(square120, new Position (1, 12, 0));
		
		rock = new Rock();
		square1 = new Square(Direction.NORTH);
		square2 = new Square(Direction.SOUTH);

		dungeon.addSquare(rock, new Position (5, 10, 0));
		dungeon.addSquare(square1, new Position (6, 10, 0));
		dungeon.addSquare(square2, new Position (5, 11, 0));
		
		ArrayList<Square> destinations = new ArrayList<Square>();
		destinations.add(square100);
		teleportSquare = new NormalTeleport(destinations,Direction.EAST);
		dungeon.addSquare(teleportSquare, new Position (0,13,0));
	}
	private static Dungeon<Square> dungeon;
	private static Square square000;
	private static Square square010;
	private static Square square100;
	private static Square square110;
	private static Square square120;
	private static Square square020;
	private static Position position000;
	private static Position position100;
	private static Position position010;

	private static Rock rock;
	private static Square square1;
	private static Square square2;
	private static NormalTeleport teleportSquare;
	@Before
	public void setUp() throws Exception { 	

	}	
	
	@Test
	public final void setMaxXCoord(){
		dungeon.setMaxXCoord(30);
		assertEquals( 30, dungeon.getMaxXCoord());
	}
	
	@Test
	public final void canHaveAsNewMaxCoord_FalseCase(){
		assertFalse(Dungeon.isValidNewMaxCoord(20, 20));
	}
	
	@Test
	public final void canHaveAsNewMaxCoord_TrueCase(){
		assertTrue(Dungeon.isValidNewMaxCoord(40, 21));
	}
	
	
	@Test
	public final void containsSquare_TrueCase(){
		assertTrue (dungeon.containsSquare(square000));
		assertTrue (dungeon.containsSquare(square100));
	}
	
	@Test
	public final void containsPosition_TrueCase(){
		assertTrue (dungeon.containsPosition(position000));
		assertTrue (dungeon.containsPosition(position010));
	}
	
	
	@Test
	public final void returnOriginalPosition_EqualCase(){
		assertEquals (position100, dungeon.returnOriginalPosition (new Position(1,10,0)));
	}	
	
	@Test
	public final void getNbOfSquares_EqualCase(){
		assertEquals (10, dungeon.getNbOfSquares());
	}
	
	@Test
	public final void getSquareFromPosition_EqualCase(){
		assertEquals(dungeon.getSquareFromPosition(position000), square000);
	}
	
	@Test
	public final void getNbOfSlipperySquares_EqualCase(){
		assertEquals (dungeon.getNbOfSlipperySquares(), 1);
	}
	
	@Test
	public final void areNeighbouringPositions_TrueCase(){
		assertTrue (dungeon.areNeighbouringPositions(position000, position100));
	}
	
	@Test
	public final void areNeighbours_TrueCase(){
		assertTrue (dungeon.areNeighbours(square000, square010));
		
	}
	
	@Test
	public final void canHaveSquareAtPosition_TrueCase(){
		assertTrue(dungeon.canHaveSquareAtPosition(new Square(), new Position(15,15,0)));
	}
	
	@Test
	public final void canHaveSquareAtPosition_FalseCase(){
		assertFalse(dungeon.canHaveSquareAtPosition(new Transparent(),new Position (5, 9, 0)));
	}

	@Test
	public final void hasOpenNeighbour_TrueCase(){
		assertTrue(dungeon.hasOpenNeighbours(square110));
		assertTrue(dungeon.hasOpenNeighbours(square120));
	}
	
	@Test
	public final void hasOpenNeighbour_FalseCase(){
		assertFalse(dungeon.hasOpenNeighbours(square100));
	}
	
	
	@Test
	public final void areInSameSpace_TrueCase(){
		assertTrue (dungeon.areInSameSpace(square000, square010));
	}
	
	@Test
	public final void areInSameSpace_FalseCase(){
		assertFalse (dungeon.areInSameSpace(square000, square100));
	}
	
	@Test
	public final void sizeOfSpaceWithSquare_EqualCase(){
		assertEquals (4,dungeon.sizeOfSpaceWithSquare(square000));
	}
	
	@Test
	public final void areTemperaturesBalanced_TrueCase(){
		dungeon.balanceSpaces();
		assertTrue (dungeon.areTemperaturesBalanced());
	}
	
	@Test
	public final void areTemperaturesBalanced_FalseCase(){
		Temperature temperature = new Temperature(new BigDecimal("20"), TemperatureScale.CELCIUS);
		square000.setTemperature(temperature);
		assertFalse (dungeon.areTemperaturesBalanced());
	}
	
	@Test
	public final void areHumiditiesBalanced_TrueCase(){
		dungeon.balanceSpaces();
		assertTrue (dungeon.areHumiditiesBalanced());
	}
	@Test
	public final void areHumiditiesBalanced_FalseCase(){
		square000.setHumidity(new BigDecimal ("5"));
		assertFalse (dungeon.areHumiditiesBalanced());
	}
	
	@Test public final void rockTemperatureTest(){
		assertTrue(rock.getTemperature().getValue(TemperatureScale.CELCIUS).equals(new BigDecimal("25")));
	}
	
	@Test
	public final void canNavigateTo_TrueCases(){
		assertTrue(dungeon.canNavigateTo(teleportSquare, square100));
		assertTrue(dungeon.canNavigateTo(teleportSquare,square020));
	}
	@Test
	public final void canNavigateTo_FalseCases(){
		assertFalse(dungeon.canNavigateTo(teleportSquare, square1));
		assertFalse(dungeon.canNavigateTo(teleportSquare, square110));
	}
}
